package com.szgz.platform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.szgz.platform.enums.EnvTypeEnum;
import com.szgz.platform.exception.BusinessException;
import com.szgz.platform.mapper.TeacherEnvironmentMapper;
import com.szgz.platform.mapper.TeacherEnvironmentUsageMapper;
import com.szgz.platform.mapper.UserMapper;
import com.szgz.platform.model.TeacherEnvironment;
import com.szgz.platform.model.TeacherEnvironmentUsage;
import com.szgz.platform.model.User;
import com.szgz.platform.service.SharedContainerService;
import com.szgz.platform.service.TeacherEnvironmentService;
import com.szgz.platform.service.TeacherEnvironmentUsageService;
import com.szgz.platform.service.UserManagementService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

import static com.szgz.platform.constants.DockerConstant.*;

@Service
@Slf4j
public class TeacherEnvironmentServiceImpl extends ServiceImpl<TeacherEnvironmentMapper, TeacherEnvironment> implements TeacherEnvironmentService {

    private final TeacherEnvironmentMapper envMapper;
    private final TeacherEnvironmentUsageMapper usageMapper;
    private final UserMapper userMapper;

    @Resource
    private SharedContainerService sharedContainerService;

    @Resource
    private TeacherEnvironmentUsageService usageService;

    @Resource
    private UserManagementService userManagementService;


    public TeacherEnvironmentServiceImpl(TeacherEnvironmentMapper envMapper, TeacherEnvironmentUsageMapper usageMapper, UserMapper userMapper) {
        this.envMapper = envMapper;
        this.usageMapper = usageMapper;
        this.userMapper = userMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TeacherEnvironment create(TeacherEnvironment env) {
        envMapper.insert(env);
        String type = env.getType();
        if (type.equals(EnvTypeEnum.MYSQL.getType())) {
            this.createSharedMySQLEnvironment(env);
        } else if (type.equals(EnvTypeEnum.IDE.getType())) {
            this.createSharedIDEEnvironment(env);
        } else if (type.equals(EnvTypeEnum.JUPYTER_HUB.getType())) {
            this.createSharedJupyterHubEnvironment(env);
        }

        return env;
    }

    @Override
    public TeacherEnvironment getById(String environmentId) {
        return envMapper.selectById(environmentId);
    }

    @Override
    public Page<TeacherEnvironment> page(long pageNum, long pageSize, String teacherId, String groupId, String type, String status) {
        LambdaQueryWrapper<TeacherEnvironment> qw = new LambdaQueryWrapper<>();
        qw.eq(TeacherEnvironment::getDeleted, 0);
        if (teacherId != null && !teacherId.isBlank()) qw.eq(TeacherEnvironment::getTeacherId, teacherId);
        if (groupId != null && !groupId.isBlank()) qw.eq(TeacherEnvironment::getGroupId, groupId);
        if (type != null && !type.isBlank()) qw.eq(TeacherEnvironment::getType, type);
        if (status != null && !status.isBlank()) qw.eq(TeacherEnvironment::getStatus, status);
        qw.orderByDesc(TeacherEnvironment::getCreatedAt);
        return envMapper.selectPage(new Page<>(pageNum, pageSize), qw);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteEnvironment(String environmentId) {
        try {
            // 1. 获取环境信息
            TeacherEnvironment environment = this.getById(environmentId);
            if (environment == null) {
                log.warn("环境不存在: {}", environmentId);
                throw new BusinessException("环境不存在");
            }

            // 2. 获取所有学生访问记录
            List<TeacherEnvironmentUsage> usages = this.listUsages(environmentId);
            log.info("删除环境 {}，发现 {} 个学生访问记录", environmentId, usages.size());

            // 3. 级联删除学生访问数据
            if (!usages.isEmpty()) {
                for (TeacherEnvironmentUsage usage : usages) {
                    try {
                        // 删除数据库账户和数据（如果是数据库类型）
                        if (EnvTypeEnum.MYSQL.getType().equals(environment.getType())) {
                            deleteMySQLUserAndDatabase(usage);
                        }
                        // 删除其他类型的资源（如Jupyter用户等）
                        else if (EnvTypeEnum.JUPYTER_HUB.getType().equals(environment.getType())) {
                            deleteJupyterUser(usage);
                        }
                    } catch (Exception e) {
                        log.error("删除学生访问资源失败: usageId={}, error={}", usage.getId(), e.getMessage(), e);
                        // 继续删除其他资源，不中断整个删除流程
                    }
                }

                // 批量删除访问记录
                List<String> usageIds = usages.stream().map(TeacherEnvironmentUsage::getId).toList();
                usageMapper.deleteBatchIds(usageIds);
                log.info("已删除 {} 个学生访问记录", usageIds.size());
            }

            // 4. 删除Docker容器实例
            try {
                deleteDockerContainer(environment);
            } catch (Exception e) {
                log.error("删除Docker容器失败: environmentId={}, error={}", environmentId, e.getMessage(), e);
                // 容器删除失败不影响数据库记录删除
            }

            // 5. 删除环境记录
            boolean result = envMapper.deleteById(environmentId) > 0;
            if (result) {
                log.info("环境删除成功: {}", environmentId);
            }
            return result;

        } catch (Exception e) {
            log.error("删除环境失败: environmentId={}, error={}", environmentId, e.getMessage(), e);
            throw new BusinessException("删除环境失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<TeacherEnvironmentUsage> bindStudents(String environmentId, List<TeacherEnvironmentUsage> usages) {
        TeacherEnvironment environment = this.getById(environmentId);
        List<TeacherEnvironmentUsage> addList = new ArrayList<>();
        for (TeacherEnvironmentUsage u : usages) {
            TeacherEnvironmentUsage usage = usageService.lambdaQuery().eq(TeacherEnvironmentUsage::getEnvironmentId, environmentId)
                    .eq(TeacherEnvironmentUsage::getStudentNo, u.getStudentNo())
                    .one();
            if (usage != null) {
                log.warn("学生已存在访问记录: studentNo={}", u.getStudentNo());
                continue;
            }
            u.setEnvironmentId(environmentId);
            // 通过学号/用户名回填 studentId
            if (u.getStudentId() == null || u.getStudentId().isBlank()) {
                String no = u.getStudentNo();
                if (no != null && !no.isBlank()) {
                    User found = userMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<User>().lambda()
                            .eq(User::getUsername, no).last("limit 1"));
                    if (found != null) {
                        u.setStudentId(found.getUserId());
                        if (u.getDisplayName() == null || u.getDisplayName().isBlank()) {
                            u.setDisplayName(found.getUsername());
                        }
                    }
                }
            }
            u.setAccessUrl(environment.getBaseUrl());
            u.setAllocatedPort(environment.getPortMapping());
            u.setServiceType(environment.getType());
            if (environment.getType().equals(EnvTypeEnum.MYSQL.getType())) {
                this.createMysqlSharedEnvStudentAccounts(environment.getContainerName(), u);
            }
            addList.add(u);
        }
        if (environment.getType().equals(EnvTypeEnum.MYSQL.getType())) {
            // MySQL环境的学生账户已在上面的循环中创建
        } else if (environment.getType().equals(EnvTypeEnum.IDE.getType())) {
            this.updateSharedIDEEnvironmentWithStudents(environment, addList);
        } else if (environment.getType().equals(EnvTypeEnum.JUPYTER_HUB.getType())) {
            this.createSharedJupyterHubAccount(environment, addList);
        }
        usageService.saveBatch(addList);
        return usages;
    }

    @Override
    public List<TeacherEnvironmentUsage> listUsages(String environmentId) {
        return usageMapper.selectList(new LambdaQueryWrapper<TeacherEnvironmentUsage>()
                .eq(TeacherEnvironmentUsage::getEnvironmentId, environmentId)
                .eq(TeacherEnvironmentUsage::getDeleted, 0)
                .orderByAsc(TeacherEnvironmentUsage::getUsername)
        );
    }

    @Override
    public Page<TeacherEnvironmentUsage> pageUsages(String environmentId, long pageNum, long pageSize) {
        return usageMapper.selectPage(new Page<>(pageNum, pageSize), new LambdaQueryWrapper<TeacherEnvironmentUsage>()
                .eq(TeacherEnvironmentUsage::getEnvironmentId, environmentId)
                .eq(TeacherEnvironmentUsage::getDeleted, 0)
                .orderByAsc(TeacherEnvironmentUsage::getUsername)
        );
    }

    @Override
    public TeacherEnvironmentUsage updateUsage(TeacherEnvironmentUsage usage) {
        usageMapper.updateById(usage);
        return usageMapper.selectById(usage.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteUsage(String usageId) {
        try {
            // 1. 获取使用记录信息
            TeacherEnvironmentUsage usage = usageMapper.selectById(usageId);
            if (usage == null) {
                log.warn("使用记录不存在: {}", usageId);
                return false;
            }

            // 2. 获取环境信息
            TeacherEnvironment environment = this.getById(usage.getEnvironmentId());
            if (environment == null) {
                log.warn("环境不存在: {}", usage.getEnvironmentId());
                return false;
            }

            // 3. 级联删除相关资源
            try {
                // 删除数据库账户和数据（如果是数据库类型）
                if (EnvTypeEnum.MYSQL.getType().equals(environment.getType())) {
                    deleteMySQLUserAndDatabase(usage);
                }
                // 删除其他类型的资源（如Jupyter用户等）
                else if (EnvTypeEnum.JUPYTER_HUB.getType().equals(environment.getType())) {
                    deleteJupyterUser(usage);
                }
                // 可以在这里添加其他类型的资源删除逻辑
            } catch (Exception e) {
                log.error("删除学生访问资源失败: usageId={}, error={}", usageId, e.getMessage(), e);
                // 资源删除失败不影响数据库记录删除，但记录错误
            }

            // 4. 删除使用记录
            boolean result = usageMapper.deleteById(usageId) > 0;
            if (result) {
                log.info("学生访问记录删除成功: usageId={}, student={}", usageId, usage.getDisplayName());
            }
            return result;

        } catch (Exception e) {
            log.error("删除学生访问记录失败: usageId={}, error={}", usageId, e.getMessage(), e);
            throw new BusinessException("删除学生访问记录失败: " + e.getMessage());
        }
    }

    @Override
    public boolean updateStatus(String environmentId, String status) {
        TeacherEnvironment env = envMapper.selectById(environmentId);
        if (env == null) return false;
        env.setStatus(status);
        env.setUpdatedAt(java.time.LocalDateTime.now());
        return envMapper.updateById(env) > 0;
    }


    private void createSharedMySQLEnvironment(TeacherEnvironment environment) {
        java.util.Objects.requireNonNull(environment.getEnvironmentId(), "groupId");
        String groupId = environment.getEnvironmentId();
        try {
            String groupDir = SHARED_DIR + "/" + groupId + "-mysql";
            java.nio.file.Files.createDirectories(java.nio.file.Paths.get(groupDir));

            // 统一使用一个对外端口
            int mysqlPort = sharedContainerService.allocatePort();

            // 生成 docker-compose.yml
            String compose = new StringBuilder()
                    .append("services:\n")
                    .append("  mysql-shared-").append(groupId).append(":\n")
                    .append("    image: mysql:5.7\n")
                    .append("    container_name: mysql-shared-").append(groupId).append("\n")
                    .append("    ports:\n")
                    .append("      - \"").append(mysqlPort).append(":3306\"\n")
                    .append("    environment:\n")
                    .append("      MYSQL_ROOT_PASSWORD: 123456\n")
                    .append("    volumes:\n")
                    .append("      - shared-").append(groupId).append("-mysql-data:/var/lib/mysql\n")
                    .append("    command: --default-authentication-plugin=mysql_native_password\n")
                    .append("    restart: unless-stopped\n")
                    .append("    networks:\n")
                    .append("      - shared-").append(groupId).append("-mysql-net\n\n")
                    .append("volumes:\n")
                    .append("  shared-").append(groupId).append("-mysql-data:\n")
                    .append("    driver: local\n\n")
                    .append("networks:\n")
                    .append("  shared-").append(groupId).append("-mysql-net:\n")
                    .append("    driver: bridge\n")
                    .toString();

            java.nio.file.Files.write(java.nio.file.Paths.get(groupDir, "docker-compose.yml"), compose.getBytes());

            // 启动容器
            ProcessBuilder up = sharedContainerService.pbDocker("compose", "up", "-d");
            up.directory(new java.io.File(groupDir));
            Process upProc = up.start();
            upProc.waitFor();

            String containerName = MYSQL_SHARED_PREFIX + groupId;

            environment.setContainerName(containerName);
            environment.setBaseUrl(BASE_URL + ":" + mysqlPort);
            environment.setPortMapping(mysqlPort + "");
            environment.setStatus("running");
            environment.setConfigJson("account: root;" + "password: 123456");
            environment.setUpdatedAt(java.time.LocalDateTime.now());

            envMapper.updateById(environment);
        } catch (Exception e) {
            log.error("创建共享MySQL资源环境失败 failed", e);
            throw new BusinessException("创建共享MySQL资源环境失败 failed: " + e.getMessage());
        }
    }


    private void createMysqlSharedEnvStudentAccounts(String containerName, TeacherEnvironmentUsage usage) {

        String mysqlUser = ("u" + usage.getStudentNo());
        usage.setDbUsername(mysqlUser);
        String dbName = mysqlUser + "_db";
        usage.setDbName(dbName);
        String password = "p" + usage.getStudentNo(); // 可后续改为按需生成
        usage.setDbPassword(password);

        String sql = "mysql -uroot -p123456 -e \""
                + "CREATE USER IF NOT EXISTS '" + mysqlUser + "'@'%' IDENTIFIED BY '" + password + "'; "
                + "CREATE DATABASE IF NOT EXISTS " + dbName + " DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; "
                + "ALTER DATABASE " + dbName + " CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; "
                + "GRANT ALL PRIVILEGES ON " + dbName + ".* TO '" + mysqlUser + "'@'%'; "
                + "FLUSH PRIVILEGES;"
                + "\"";

        try {
            ProcessBuilder exec = sharedContainerService.pbDocker("exec", containerName, "sh", "-lc", sql);
            Process ep = exec.start();
            int exit = ep.waitFor();
            if (exit != 0) {
                String err = new String(ep.getErrorStream().readAllBytes());
                throw new RuntimeException("配置 MySQL 用户失败： " + usage.getStudentNo() + ": " + err);
            }
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * 创建共享IDE环境
     */
    private void createSharedIDEEnvironment(TeacherEnvironment environment) {
        String groupId = environment.getEnvironmentId();
        try {
            log.info("开始创建共享IDE环境: groupId={}", groupId);
            
            // 创建一个空的学生列表，学生将在后续的bindStudents方法中添加
            List<String> emptyStudentIds = new ArrayList<>();
            
            // 调用UserManagementService创建共享IDE环境
            Map<String, Object> result = userManagementService.createSharedIDEEnvironment(groupId, emptyStudentIds);
            
            // 更新TeacherEnvironment的状态和信息
            String environmentId = (String) result.get("environmentId");
            environment.setStatus("RUNNING");
            environment.setContainerName("ide-shared-" + groupId);
            environment.setBaseUrl("http://192.168.1.168"); // 基础URL，具体端口在学生绑定时分配
            
            // 更新数据库记录
            envMapper.updateById(environment);
            
            log.info("共享IDE环境创建成功: groupId={}, environmentId={}", groupId, environmentId);
            
        } catch (Exception e) {
            log.error("创建共享IDE环境失败: groupId={}, error={}", groupId, e.getMessage(), e);
            environment.setStatus("ERROR");
            envMapper.updateById(environment);
            throw new RuntimeException("创建共享IDE环境失败: " + e.getMessage(), e);
        }
    }

    /**
     * 更新共享IDE环境，添加新学生
     */
    private void updateSharedIDEEnvironmentWithStudents(TeacherEnvironment environment, List<TeacherEnvironmentUsage> newUsages) {
        String groupId = environment.getEnvironmentId();
        try {
            log.info("更新共享IDE环境，添加学生: groupId={}, newStudents={}", groupId, newUsages.size());
            
            // 获取所有现有学生（包括新添加的）
            List<TeacherEnvironmentUsage> allUsages = this.listUsages(environment.getEnvironmentId());
            List<String> allStudentIds = new ArrayList<>();
            
            // 收集所有学生ID
            for (TeacherEnvironmentUsage usage : allUsages) {
                if (usage.getStudentNo() != null && !usage.getStudentNo().trim().isEmpty()) {
                    allStudentIds.add(usage.getStudentNo().trim());
                }
            }
            
            // 添加新学生ID
            for (TeacherEnvironmentUsage usage : newUsages) {
                if (usage.getStudentNo() != null && !usage.getStudentNo().trim().isEmpty()) {
                    String studentId = usage.getStudentNo().trim();
                    if (!allStudentIds.contains(studentId)) {
                        allStudentIds.add(studentId);
                    }
                }
            }
            
            // 删除现有的共享IDE环境
            try {
                userManagementService.deleteSharedIDEEnvironment(groupId);
                log.info("已删除旧的共享IDE环境: groupId={}", groupId);
            } catch (Exception e) {
                log.warn("删除旧共享IDE环境失败，继续创建新环境: groupId={}, error={}", groupId, e.getMessage());
            }
            
            // 重新创建包含所有学生的共享IDE环境
            Map<String, Object> result = userManagementService.createSharedIDEEnvironment(groupId, allStudentIds);
            
            // 更新新学生的访问信息
            @SuppressWarnings("unchecked")
            Map<String, Integer> studentToPort = (Map<String, Integer>) result.get("ports");
            @SuppressWarnings("unchecked")
            Map<String, String> studentToUrl = (Map<String, String>) result.get("urls");
            
            for (TeacherEnvironmentUsage usage : newUsages) {
                String studentNo = usage.getStudentNo();
                if (studentNo != null && studentToPort.containsKey(studentNo)) {
                    Integer port = studentToPort.get(studentNo);
                    String url = studentToUrl.get(studentNo);
                    
                    usage.setAllocatedPort(port.toString());
                    usage.setAccessUrl(url);
                    usage.setAccessUsername(studentNo);
                    usage.setAccessPassword("password"); // 默认密码，可以后续修改
                    usage.setWorkDir("/workspace/" + studentNo);
                    
                    log.info("学生IDE访问信息已设置: studentNo={}, port={}, url={}", studentNo, port, url);
                }
            }
            
            log.info("共享IDE环境更新成功: groupId={}, totalStudents={}", groupId, allStudentIds.size());
            
        } catch (Exception e) {
            log.error("更新共享IDE环境失败: groupId={}, error={}", groupId, e.getMessage(), e);
            throw new RuntimeException("更新共享IDE环境失败: " + e.getMessage(), e);
        }
    }

    private void createSharedJupyterHubEnvironment(TeacherEnvironment environment) {
        String groupId = environment.getEnvironmentId();
        try {
            String groupDir = SHARED_DIR + "/" + groupId + "-jhub";
            Files.createDirectories(Paths.get(groupDir));

            int hubPort = sharedContainerService.allocatePort();

            // 1. 首先生成配置文件（包含默认配置）
            String defaultConfig = String.join("\n",
                "c = get_config()",
                "c.JupyterHub.bind_url = 'http://:8000'",
                "c.JupyterHub.base_url = '/jhub/'",
                "c.Spawner.default_url = '/lab'",
                "# Hub 默认 8000 端口，容器间通过网络名访问 jhub-{groupId}:8000",
                "c.JupyterHub.hub_ip = '0.0.0.0'",
                "c.JupyterHub.hub_connect_ip = 'jhub-" + groupId + "'",
                "# 使用默认 8000，无需额外 hub_connect_url",
                "# Spawner 配置",
                "from dockerspawner import DockerSpawner",
                "c.JupyterHub.spawner_class = DockerSpawner",
                "c.DockerSpawner.image = 'jupyterhub/singleuser:latest'",
                "c.DockerSpawner.network_name = 'jhub-" + groupId + "-net'",
                "c.DockerSpawner.use_internal_ip = True",
                "c.DockerSpawner.notebook_dir = '/home/jovyan/work'",
                "c.DockerSpawner.remove = True",
                "c.DockerSpawner.volumes = { 'jhub-{username}': '/home/jovyan/work' }",
                "# 中文语言环境配置",
                "c.DockerSpawner.environment = {",
                "    'LANG': 'zh_CN.UTF-8',",
                "    'LC_ALL': 'zh_CN.UTF-8',",
                "    'LANGUAGE': 'zh_CN:zh',",
                "    'JUPYTER_ENABLE_LAB': 'yes'",
                "}",
                "# 启动/健康检查超时",
                "c.Spawner.start_timeout = 180",
                "c.Spawner.http_timeout = 180",
                "# 认证（演示用）",
                "from jupyterhub.auth import DummyAuthenticator",
                "c.JupyterHub.authenticator_class = DummyAuthenticator",
                "c.DummyAuthenticator.password = 'pass'",
                "c.Authenticator.allowed_users = []",
                "# 平台服务令牌（初始为空，后续更新）",
                "c.JupyterHub.services = []"
            );
            
            // 写入初始配置文件
            Files.write(Paths.get(groupDir, "jupyterhub_config.py"), defaultConfig.getBytes(StandardCharsets.UTF_8));
            log.info("已创建初始JupyterHub配置文件: {}", groupDir);

            // 2. 写入 docker-compose.yml
            String compose = new StringBuilder()
                    .append("services:\n")
                    .append("  jhub-").append(groupId).append(":\n")
                    .append("    image: jupyterhub/jupyterhub:latest\n")
                    .append("    container_name: jhub-").append(groupId).append("\n")
                    .append("    ports:\n")
                    .append("      - \"").append(hubPort).append(":8000\"\n")
                    .append("    volumes:\n")
                    .append("      - ./jupyterhub_config.py:/srv/jupyterhub/jupyterhub_config.py\n")
                    .append("      - /var/run/docker.sock:/var/run/docker.sock\n")
                    .append("      - hub-data:/srv/jupyterhub\n")
                    .append("    command: bash -c \"python3 -m pip install --no-cache-dir dockerspawner && jupyterhub -f /srv/jupyterhub/jupyterhub_config.py\"\n")
                    .append("    networks:\n")
                    .append("      - jhub-").append(groupId).append("-net\n")
                    .append("    restart: unless-stopped\n\n")
                    .append("volumes:\n")
                    .append("  hub-data:\n")
                    .append("    driver: local\n\n")
                    .append("networks:\n")
                    .append("  jhub-").append(groupId).append("-net:\n")
                    .append("    name: jhub-").append(groupId).append("-net\n")
                    .append("    driver: bridge\n")
                    .toString();
            Files.write(Paths.get(groupDir, "docker-compose.yml"), compose.getBytes());

            // 3. 启动 Hub
            log.info("启动JupyterHub容器: {}", groupDir);
            ProcessBuilder up = sharedContainerService.pbDocker("compose", "up", "-d");
            up.directory(new File(groupDir));
            Process upProc = up.start();
            int exitCode = upProc.waitFor();
            
            if (exitCode != 0) {
                String errorOutput = new String(upProc.getErrorStream().readAllBytes());
                log.error("启动JupyterHub容器失败: exitCode={}, error={}", exitCode, errorOutput);
                throw new RuntimeException("启动JupyterHub容器失败: exitCode=" + exitCode);
            }

            String containerName = "jhub-" + groupId;
            log.info("等待JupyterHub容器就绪: {}", containerName);
            waitForContainerReady(containerName, 45);

            // 4. 更新环境信息
            environment.setContainerName(containerName);
            environment.setBaseUrl(BASE_URL + ":" + hubPort + "/jhub/hub/login");
            environment.setPortMapping(hubPort + "");
            environment.setStatus("running");
            environment.setUpdatedAt(java.time.LocalDateTime.now());
            
            // 5. 保存环境信息到数据库
            envMapper.updateById(environment);
            log.info("JupyterHub环境创建成功: container={}, port={}", containerName, hubPort);

        } catch (Exception e) {
            log.error("创建JupyterHub资源失败: groupId={}, error={}", groupId, e.getMessage(), e);
            // 清理已分配的资源
            try {
                cleanupJupyterHubResources(groupId);
            } catch (Exception cleanupEx) {
                log.warn("清理JupyterHub资源失败: {}", cleanupEx.getMessage());
            }
            throw new BusinessException("创建JupyterHub资源失败: " + e.getMessage());
        }
    }


    private void createSharedJupyterHubAccount(TeacherEnvironment environment, List<TeacherEnvironmentUsage> usageList) {
        log.info("创建JupyterHub账户: environmentId={}, users={}", environment.getEnvironmentId(), usageList.size());
        
        try {
            String environmentId = environment.getEnvironmentId();
            String groupDir = SHARED_DIR + "/" + environmentId + "-jhub";
            String containerName = environment.getContainerName();
            
            if (containerName == null || containerName.isBlank()) {
                log.error("容器名称为空，无法创建JupyterHub账户: environmentId={}", environmentId);
                throw new RuntimeException("容器名称为空");
            }
            
            // 1. 生成新的API Token（如果还没有的话）
            String apiToken = environment.getApiToken();
            if (apiToken == null || apiToken.isBlank()) {
                apiToken = java.util.UUID.randomUUID().toString().replace("-", "");
                environment.setApiToken(apiToken);
                envMapper.updateById(environment);
                log.info("已生成新的JupyterHub API Token");
            }
            
            // 2. 更新配置文件，添加新用户到allowed_users列表
            updateJupyterHubConfigWithUsers(groupDir, environmentId, apiToken, usageList);
            
            // 3. 重新加载JupyterHub配置
            boolean reloadSuccess = reloadJupyterHubConfig(containerName);
            if (!reloadSuccess) {
                log.warn("配置重载失败，将使用API方式创建用户: {}", containerName);
            }
            
            // 4. 通过 Hub API 批量创建用户（作为备选方案）
            if (!reloadSuccess) {
                String hubBase = "http://127.0.0.1:" + environment.getPortMapping();
                log.info("开始通过API创建JupyterHub用户: baseUrl={}", hubBase);
                
                // 等待 Hub /hub/health 就绪（减少超时时间到5秒）
                boolean hubReady = awaitHubReady(hubBase, 5);
                
                if (!hubReady) {
                    log.warn("JupyterHub服务未就绪，尝试直接创建用户");
                    // 即使健康检查失败，也尝试直接创建用户
                }
                
                // 批量创建用户
                int successCount = awaitCreateUsers(hubBase, apiToken, usageList);
                
                log.info("JupyterHub账户创建完成: 成功={}/{}, environmentId={}", 
                        successCount, usageList.size(), environmentId);
            } else {
                log.info("JupyterHub配置重载成功，用户已通过配置文件添加: environmentId={}, users={}", 
                        environmentId, usageList.size());
            }
                    
        } catch (Exception e) {
            log.error("创建JupyterHub账户失败: environmentId={}, error={}", 
                    environment.getEnvironmentId(), e.getMessage(), e);
            throw new RuntimeException("创建JupyterHub账户失败: " + e.getMessage(), e);
        }
    }


    private void waitForContainerReady(String containerName, int timeoutSeconds) throws Exception {
        sharedContainerService.waitForContainerReady(containerName, timeoutSeconds);
    }

    private void hubApiCreateUser(String hubBase, String apiToken, String username) throws Exception {
        String url = hubBase + "/jhub/hub/api/users/" + java.net.URLEncoder.encode(username, java.nio.charset.StandardCharsets.UTF_8);
        
        log.debug("调用JupyterHub API创建用户: {}", url);
        
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Authorization", "token " + apiToken);
        conn.setRequestProperty("Content-Type", "application/json");
        conn.setConnectTimeout(5000);  // 5秒连接超时
        conn.setReadTimeout(10000);    // 10秒读取超时
        conn.setDoOutput(true);
        
        try {
            // 发送空请求体
            conn.getOutputStream().write(new byte[0]);
            
            int code = conn.getResponseCode();
            String responseMessage = conn.getResponseMessage();
            
            log.debug("JupyterHub API响应: {} {}", code, responseMessage);
            
            if (code >= 400) {
                // 读取错误响应
                String errorResponse = "";
                try {
                    errorResponse = new String(conn.getErrorStream().readAllBytes());
                } catch (Exception e) {
                    log.warn("无法读取错误响应: {}", e.getMessage());
                }
                
                String errorMsg = String.format("Hub API create user failed, code=%d, message=%s, response=%s", 
                    code, responseMessage, errorResponse);
                log.error(errorMsg);
                throw new RuntimeException(errorMsg);
            }
            
            log.debug("成功创建JupyterHub用户: {}", username);
            
        } finally {
            conn.disconnect();
        }
    }

    /**
     * 删除MySQL用户和数据库
     */
    private void deleteMySQLUserAndDatabase(TeacherEnvironmentUsage usage) {
        try {
            String dbName = usage.getDbName();
            String dbUsername = usage.getDbUsername();

            // 获取环境信息以获取容器名称
            TeacherEnvironment environment = this.getById(usage.getEnvironmentId());
            if (environment == null) {
                log.warn("无法获取环境信息，跳过MySQL资源删除: usageId={}", usage.getId());
                return;
            }

            String containerName = environment.getContainerName();
            if (containerName == null || containerName.isBlank()) {
                log.warn("容器名称为空，跳过MySQL资源删除: usageId={}", usage.getId());
                return;
            }

            log.info("开始删除MySQL资源: usageId={}, container={}, dbName={}, dbUsername={}",
                    usage.getId(), containerName, dbName, dbUsername);

            if (dbName != null && !dbName.isBlank()) {
                // 使用Docker exec删除数据库
                executeMySQLCommandInContainer(containerName, "DROP DATABASE IF EXISTS `" + dbName + "`");
                log.info("已删除数据库: {}", dbName);
            }

            if (dbUsername != null && !dbUsername.isBlank()) {
                // 使用Docker exec删除用户
                executeMySQLCommandInContainer(containerName, "DROP USER IF EXISTS '" + dbUsername + "'@'%'");
                log.info("已删除MySQL用户: {}", dbUsername);
            }

            log.info("MySQL资源删除完成: usageId={}", usage.getId());
        } catch (Exception e) {
            log.error("删除MySQL用户和数据库失败: usageId={}, error={}", usage.getId(), e.getMessage(), e);
            // 不抛出异常，避免影响数据库记录删除
        }
    }

    /**
     * 在MySQL容器中执行MySQL命令
     */
    private void executeMySQLCommandInContainer(String containerName, String sql) {
        try {
            // 构建Docker exec命令
            String[] cmd = {
                    "docker", "exec", containerName,
                    "mysql", "-uroot", "-p123456", "-e", sql
            };

            log.debug("执行MySQL命令: {}", String.join(" ", cmd));

            ProcessBuilder pb = new ProcessBuilder(cmd);
            Process process = pb.start();

            // 等待命令执行完成
            int exitCode = process.waitFor();

            if (exitCode != 0) {
                // 读取错误输出
                String errorOutput = new String(process.getErrorStream().readAllBytes());
                log.warn("MySQL命令执行失败: {}, exitCode: {}, error: {}", sql, exitCode, errorOutput);
            } else {
                log.debug("MySQL命令执行成功: {}", sql);
            }

        } catch (Exception e) {
            log.error("在容器中执行MySQL命令失败: container={}, sql={}, error={}",
                    containerName, sql, e.getMessage(), e);
            throw new RuntimeException("在容器中执行MySQL命令失败", e);
        }
    }

    /**
     * 删除Jupyter用户
     */
    private void deleteJupyterUser(TeacherEnvironmentUsage usage) {
        try {
            String username = usage.getAccessUsername();
            if (username != null && !username.isBlank()) {
                // 这里可以调用Jupyter Hub API删除用户
                // 或者执行系统命令删除用户目录
                String userDir = "/home/" + username;
                deleteUserDirectory(userDir);
                log.info("已删除Jupyter用户目录: {}", userDir);
            }
        } catch (Exception e) {
            log.error("删除Jupyter用户失败: usageId={}, error={}", usage.getId(), e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 删除Docker容器
     */
    private void deleteDockerContainer(TeacherEnvironment environment) {
        try {
            String containerName = environment.getContainerName();
            if (containerName != null && !containerName.isBlank()) {
                // 停止并删除容器
                String stopCmd = "docker stop " + containerName;
                String rmCmd = "docker rm " + containerName;

                Process stopProcess = Runtime.getRuntime().exec(stopCmd);
                int stopExitCode = stopProcess.waitFor();
                if (stopExitCode != 0) {
                    log.warn("停止Docker容器失败: {}, exitCode: {}", containerName, stopExitCode);
                }

                Thread.sleep(2000); // 等待容器停止

                Process rmProcess = Runtime.getRuntime().exec(rmCmd);
                int rmExitCode = rmProcess.waitFor();
                if (rmExitCode != 0) {
                    log.warn("删除Docker容器失败: {}, exitCode: {}", containerName, rmExitCode);
                }

                log.info("已删除Docker容器: {}", containerName);
            }
        } catch (Exception e) {
            log.error("删除Docker容器失败: environmentId={}, error={}", environment.getEnvironmentId(), e.getMessage(), e);
            throw new RuntimeException("删除Docker容器失败", e);
        }
    }

    /**
     * 删除用户目录
     */
    private void deleteUserDirectory(String userDir) {
        try {
            File dir = new File(userDir);
            if (dir.exists()) {
                deleteDirectoryRecursively(dir);
                log.info("已删除用户目录: {}", userDir);
            }
        } catch (Exception e) {
            log.error("删除用户目录失败: {}, error={}", userDir, e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 递归删除目录
     */
    private void deleteDirectoryRecursively(File dir) {
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectoryRecursively(file);
                }
            }
        }
        if (!dir.delete()) {
            log.warn("无法删除文件/目录: {}", dir.getAbsolutePath());
        }
    }

    /**
     * 执行MySQL命令
     */
    private void executeMySQLCommand(String sql) {
        try {
            // 这里应该使用配置的MySQL连接信息
            // 为了简化，这里只是示例，实际应该使用数据库连接池
            String mysqlCmd = String.format("mysql -u%s -p%s -e \"%s\"",
                    "root", "root", sql);

            Process process = Runtime.getRuntime().exec(mysqlCmd);
            int exitCode = process.waitFor();

            if (exitCode != 0) {
                log.error("MySQL命令执行失败: {}, exitCode: {}", sql, exitCode);
                throw new RuntimeException("MySQL命令执行失败");
            }
        } catch (Exception e) {
            log.error("执行MySQL命令失败: {}, error={}", sql, e.getMessage(), e);
            throw new RuntimeException("执行MySQL命令失败", e);
        }
    }

    /**
     * 清理JupyterHub资源（创建失败时的回滚操作）
     */
    private void cleanupJupyterHubResources(String groupId) {
        try {
            String groupDir = SHARED_DIR + "/" + groupId + "-jhub";
            String containerName = "jhub-" + groupId;
            
            log.info("清理JupyterHub资源: groupId={}, container={}", groupId, containerName);
            
            // 1. 停止并删除容器
            try {
                ProcessBuilder stop = sharedContainerService.pbDocker("stop", containerName);
                Process stopProc = stop.start();
                stopProc.waitFor();
                
                ProcessBuilder rm = sharedContainerService.pbDocker("rm", containerName);
                Process rmProc = rm.start();
                rmProc.waitFor();
                
                log.info("已清理JupyterHub容器: {}", containerName);
            } catch (Exception e) {
                log.warn("清理JupyterHub容器失败: {}", e.getMessage());
            }
            
            // 2. 删除目录
            try {
                File dir = new File(groupDir);
                if (dir.exists()) {
                    deleteDirectoryRecursively(dir);
                    log.info("已清理JupyterHub目录: {}", groupDir);
                }
            } catch (Exception e) {
                log.warn("清理JupyterHub目录失败: {}", e.getMessage());
            }
            
            // 3. 释放端口（这里需要实现端口释放逻辑）
            // TODO: 实现端口释放逻辑
            
        } catch (Exception e) {
            log.error("清理JupyterHub资源失败: groupId={}, error={}", groupId, e.getMessage(), e);
        }
    }

    /**
     * 等待JupyterHub服务就绪
     */
    private boolean awaitHubReady(String hubBase, int timeoutSeconds) {
        log.info("等待JupyterHub服务就绪: baseUrl={}, timeout={}s", hubBase, timeoutSeconds);
        
        // 大幅减少检查间隔到100ms，提高响应速度
        for (int i = 0; i < timeoutSeconds * 10; i++) {
            try {
                URL u = new URL(hubBase + "/hub/health");
                HttpURLConnection c = (HttpURLConnection) u.openConnection();
                c.setConnectTimeout(200);   // 减少连接超时到200ms
                c.setReadTimeout(500);     // 减少读取超时到500ms
                c.connect();
                int code = c.getResponseCode();
                c.disconnect();
                if (code == 200) {
                    log.info("JupyterHub服务就绪 (尝试 {}/{} 次，耗时 {:.1f}s)", 
                            i + 1, timeoutSeconds * 10, (i + 1) * 0.1);
                    return true;
                }
            } catch (Exception ignore) {
                // 忽略连接错误，继续等待
            }
            try {
                Thread.sleep(100);  // 减少等待时间到100ms
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
        
        log.warn("JupyterHub服务未就绪，超时时间: {}s", timeoutSeconds);
        return false;
    }

    /**
     * 批量创建JupyterHub用户
     */
    private int awaitCreateUsers(String hubBase, String apiToken, List<TeacherEnvironmentUsage> usageList) {
        log.info("开始批量创建JupyterHub用户: count={}", usageList.size());
        
        int successCount = 0;
        int retryCount = 0;
        int maxRetries = 3;
        
        for (TeacherEnvironmentUsage usage : usageList) {
            String username = usage.getStudentNo().trim();
            boolean userCreated = false;
            
            // 重试机制：最多重试3次
            while (!userCreated && retryCount < maxRetries) {
                try {
                    hubApiCreateUser(hubBase, apiToken, username);
                    successCount++;
                    userCreated = true;
                    log.debug("成功创建JupyterHub用户: {}", username);
                    retryCount = 0; // 重置重试计数
                    
                } catch (Exception ex) {
                    retryCount++;
                    if (retryCount >= maxRetries) {
                        log.warn("创建JupyterHub用户失败，已达到最大重试次数: {}, error: {}", username, ex.getMessage());
                    } else {
                        log.warn("创建JupyterHub用户失败，准备重试 ({}/{}): {}, error: {}", username, retryCount, maxRetries, ex.getMessage());
                        try {
                            Thread.sleep(1000); // 重试前等待1秒
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                            break;
                        }
                    }
                }
            }
        }
        
        log.info("JupyterHub用户创建完成: 成功={}/{}", successCount, usageList.size());
        return successCount;
    }

    /**
     * 使用API方式创建用户（当SIGHUP失败时的备选方案）
     */
    private void awaitApiUserCreation(TeacherEnvironment environment, List<TeacherEnvironmentUsage> usageList, String apiToken) {
        log.info("使用API方式创建JupyterHub用户: environmentId={}", environment.getEnvironmentId());
        
        try {
            String hubBase = "http://127.0.0.1:" + environment.getPortMapping();
            
            // 等待服务就绪
            if (awaitHubReady(hubBase, 30)) {
                int successCount = awaitCreateUsers(hubBase, apiToken, usageList);
                log.info("API方式创建用户完成: 成功={}/{}", successCount, usageList.size());
            } else {
                log.warn("JupyterHub服务未就绪，无法通过API创建用户");
            }
        } catch (Exception e) {
            log.error("API方式创建用户失败: {}", e.getMessage(), e);
        }
    }

    /**
     * 重新加载JupyterHub配置
     */
    private boolean reloadJupyterHubConfig(String containerName) {
        log.info("开始重新加载JupyterHub配置: {}", containerName);
        
        // 策略1: 尝试发送SIGHUP信号到jupyterhub进程
        if (trySIGHUPReload(containerName)) {
            return true;
        }
        
        // 策略2: 尝试重启jupyterhub服务（容器内）
        if (tryRestartJupyterHubService(containerName)) {
            return true;
        }
        
        // 策略3: 尝试使用API方式重新加载
        if (tryAPIReload(containerName)) {
            return true;
        }
        
        log.warn("所有配置重载策略都失败了");
        return false;
    }
    
    /**
     * 策略1: 使用SIGHUP信号重载配置
     */
    private boolean trySIGHUPReload(String containerName) {
        try {
            log.info("尝试策略1: 发送SIGHUP信号到jupyterhub进程");
            
            // 先找到jupyterhub进程ID
            ProcessBuilder findProc = sharedContainerService.pbDocker("exec", containerName, "pgrep", "-f", "jupyterhub");
            Process findProcess = findProc.start();
            String output = new String(findProcess.getInputStream().readAllBytes()).trim();
            findProcess.waitFor();
            
            if (output.isEmpty()) {
                log.warn("未找到jupyterhub进程");
                return false;
            }
            
            String[] pids = output.split("\n");
            for (String pid : pids) {
                if (!pid.trim().isEmpty()) {
                    try {
                        ProcessBuilder exec = sharedContainerService.pbDocker("exec", containerName, "kill", "-HUP", pid.trim());
                        Process execProc = exec.start();
                        execProc.waitFor();
                        log.info("已发送SIGHUP信号到进程: {}", pid.trim());
                    } catch (Exception e) {
                        log.warn("发送SIGHUP信号到进程 {} 失败: {}", pid.trim(), e.getMessage());
                    }
                }
            }
            
            // 等待配置重载
            Thread.sleep(5000);
            
            // 检查服务是否正常
            if (checkJupyterHubHealth(containerName)) {
                log.info("策略1成功: SIGHUP信号重载配置成功");
                return true;
            }
            
        } catch (Exception e) {
            log.warn("策略1失败: SIGHUP信号重载配置失败: {}", e.getMessage());
        }
        
        return false;
    }
    
    /**
     * 策略2: 重启容器内的jupyterhub服务
     */
    private boolean tryRestartJupyterHubService(String containerName) {
        try {
            log.info("尝试策略2: 重启容器内的jupyterhub服务");
            
            // 停止jupyterhub服务
            ProcessBuilder stopProc = sharedContainerService.pbDocker("exec", containerName, "pkill", "-f", "jupyterhub");
            Process stopProcess = stopProc.start();
            stopProcess.waitFor();
            Thread.sleep(2000);
            
            // 重新启动jupyterhub服务
            ProcessBuilder startProc = sharedContainerService.pbDocker("exec", containerName, "bash", "-c", 
                "cd /srv/jupyterhub && jupyterhub -f jupyterhub_config.py --no-ssl-check &");
            Process startProcess = startProc.start();
            startProcess.waitFor();
            
            // 等待服务启动
            Thread.sleep(10000);
            
            // 检查服务是否正常
            if (checkJupyterHubHealth(containerName)) {
                log.info("策略2成功: 重启jupyterhub服务成功");
                return true;
            }
            
        } catch (Exception e) {
            log.warn("策略2失败: 重启jupyterhub服务失败: {}", e.getMessage());
        }
        
        return false;
    }
    
    /**
     * 策略3: 使用API方式重新加载配置
     */
    private boolean tryAPIReload(String containerName) {
        try {
            log.info("尝试策略3: 使用API方式重新加载配置");
            
            // 这里可以实现通过JupyterHub API重新加载配置的逻辑
            // 但通常JupyterHub不支持通过API重新加载配置
            log.info("策略3: JupyterHub不支持通过API重新加载配置");
            return false;
            
        } catch (Exception e) {
            log.warn("策略3失败: API方式重新加载配置失败: {}", e.getMessage());
        }
        
        return false;
    }
    
    /**
     * 检查JupyterHub服务健康状态
     */
    private boolean checkJupyterHubHealth(String containerName) {
        try {
            // 检查容器内jupyterhub进程是否运行
            ProcessBuilder checkProc = sharedContainerService.pbDocker("exec", containerName, "pgrep", "-f", "jupyterhub");
            Process checkProcess = checkProc.start();
            String output = new String(checkProcess.getInputStream().readAllBytes()).trim();
            checkProcess.waitFor();
            
            if (output.isEmpty()) {
                log.warn("JupyterHub进程未运行");
                return false;
            }
            
            log.info("JupyterHub进程运行正常，进程ID: {}", output);
            return true;
            
        } catch (Exception e) {
            log.warn("检查JupyterHub健康状态失败: {}", e.getMessage());
            return false;
        }
    }
    
    /**
     * 更新JupyterHub配置文件，添加新用户到allowed_users列表
     */
    private void updateJupyterHubConfigWithUsers(String groupDir, String environmentId, String apiToken, List<TeacherEnvironmentUsage> usageList) {
        try {
            String configPath = groupDir + "/jupyterhub_config.py";
            
            // 收集所有现有用户和新用户
            Set<String> allUsers = new HashSet<>();
            
            // 从数据库获取该环境的所有现有用户
            List<TeacherEnvironmentUsage> existingUsages = usageMapper.selectList(
                new LambdaQueryWrapper<TeacherEnvironmentUsage>()
                    .eq(TeacherEnvironmentUsage::getEnvironmentId, environmentId)
            );
            
            for (TeacherEnvironmentUsage usage : existingUsages) {
                if (usage.getStudentNo() != null && !usage.getStudentNo().trim().isEmpty()) {
                    allUsers.add(usage.getStudentNo().trim());
                }
            }
            
            // 添加新用户
            for (TeacherEnvironmentUsage usage : usageList) {
                if (usage.getStudentNo() != null && !usage.getStudentNo().trim().isEmpty()) {
                    allUsers.add(usage.getStudentNo().trim());
                }
            }
            
            // 生成allowed_users字符串
            String allowedUsersStr = allUsers.stream()
                .map(user -> "'" + user.replace("'", "") + "'")
                .collect(java.util.stream.Collectors.joining(", "));
            
            log.info("更新JupyterHub配置文件，添加用户: {}", allowedUsersStr);
            
            // 生成完整的配置文件内容
            String configContent = String.join("\n",
                "c = get_config()",
                "c.JupyterHub.bind_url = 'http://:8000'",
                "c.JupyterHub.base_url = '/jhub/'",
                "c.Spawner.default_url = '/lab'",
                "# Hub 默认 8000 端口，容器间通过网络名访问 jhub-{groupId}:8000",
                "c.JupyterHub.hub_ip = '0.0.0.0'",
                "c.JupyterHub.hub_connect_ip = 'jhub-" + environmentId + "'",
                "# 使用默认 8000，无需额外 hub_connect_url",
                "# Spawner 配置",
                "from dockerspawner import DockerSpawner",
                "c.JupyterHub.spawner_class = DockerSpawner",
                "c.DockerSpawner.image = 'jupyterhub/singleuser:latest'",
                "c.DockerSpawner.network_name = 'jhub-" + environmentId + "-net'",
                "c.DockerSpawner.use_internal_ip = True",
                "c.DockerSpawner.notebook_dir = '/home/jovyan/work'",
                "c.DockerSpawner.remove = True",
                "c.DockerSpawner.volumes = { 'jhub-{username}': '/home/jovyan/work' }",
                "# 中文语言环境配置",
                "c.DockerSpawner.environment = {",
                "    'LANG': 'zh_CN.UTF-8',",
                "    'LC_ALL': 'zh_CN.UTF-8',",
                "    'LANGUAGE': 'zh_CN:zh',",
                "    'JUPYTER_ENABLE_LAB': 'yes'",
                "}",
                "# 启动/健康检查超时",
                "c.Spawner.start_timeout = 180",
                "c.Spawner.http_timeout = 180",
                "# 认证（演示用）",
                "from jupyterhub.auth import DummyAuthenticator",
                "c.JupyterHub.authenticator_class = DummyAuthenticator",
                "c.DummyAuthenticator.password = 'pass'",
                "c.Authenticator.allowed_users = [" + allowedUsersStr + "]",
                "# 平台服务令牌",
                "c.JupyterHub.services = [",
                "    {",
                "        'name': 'platform-api',",
                "        'api_token': '" + apiToken + "',",
                "    }",
                "]"
            );
            
            // 写入配置文件
            Files.write(Paths.get(configPath), configContent.getBytes(StandardCharsets.UTF_8));
            log.info("JupyterHub配置文件已更新: {}", configPath);
            
        } catch (Exception e) {
            log.error("更新JupyterHub配置文件失败: {}", e.getMessage(), e);
            throw new RuntimeException("更新JupyterHub配置文件失败: " + e.getMessage(), e);
        }
    }
}

